/*
 * StrVec.h
 *
 *  Created on: 2020年12月1日
 *      Author: san
 */

#ifndef STRVEC_H_
#define STRVEC_H_

#include <utility>
#include <string>
#include <memory>
#include <algorithm>
#include <iostream>

class StrVec {
public:

	// 构造函数和析构函数
	StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) {};
	StrVec(const StrVec &) ;
	virtual ~StrVec();
	// 移动构造函数, 注意：需要添加 noexcept
	StrVec(StrVec &&sv) noexcept ;


	// 重载赋值运算符
	StrVec &operator=(StrVec);
	std::string &operator[](std::size_t n) { return elements[n]; }
	const std::string &operator[](std::size_t n) const { return elements[n]; }

	friend void swap(StrVec &lhs, StrVec &rhs)
	{
		using std::swap;
		swap(lhs.elements, rhs.elements);
		swap(lhs.first_free, rhs.first_free);
		swap(lhs.cap, rhs.cap);
	}

	void push_back(const std::string &);

	std::size_t size() {return first_free - elements; }
	std::size_t capacity() const { return cap - elements; }
	std::string *begin() const { return elements; }
	std::string *end() const { return first_free; }

	void resize(std::size_t, const std::string &);
	void print() {std::for_each(elements, first_free, [](const std::string &s){ std::cout << s <<  std::endl;});}
private:
	static std::allocator<std::string> alloc;
    std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);  // 会分配内存，并拷贝一个给定范围内的元素
	void free();  // 销毁元素并释放内存

	void chk_n_alloc() { if (size() >= capacity()) reallocate(); };  // 保证StrVec至少有容纳一个新元素的空间。如果没有，则调用reallocate
	void reallocate();  // 在内存要用完时，分配新内存
	void alloc_n_move(std::size_t capacity);

	void reserve(std::size_t);
	std::string *elements;
	std::string *first_free;
	std::string *cap;
};

void swap(StrVec &lhs, StrVec &rhs);
//{
//	using std::swap;
//	swap(lhs.elements, rhs.elements);
//	swap(lhs.first_free, rhs.first_free);
//	swap(lhs.cap, rhs.cap);
//}
#endif /* STRVEC_H_ */
